/****************************************************
          File Name:list.c
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Wed 15 Oct 2014 06:04:36 PM CST
*****************************************************/

#include "list.h"
#include "59-4.h"

static int ori = 0; 	/* is file modified */
static socklen_t length=sizeof(struct sockaddr_in);

/* create a list from a file, not test yet */
Node *lopen(char *filename)
{
	Node *root = NULL, *cur, *pre;
	int fd;
	char *buf;
	size_t len=sizeof(Node);
	struct stat sat;
	fd=open(filename,O_RDWR);
	if(fd == -1)
    {
        errno = ENOENT;
		return (Node *)-1;
    }
	fstat(fd,&sat);
	buf=malloc(len);
    if(sat.st_size % len != 0)      /* ensure file is complete */
    {
        errno = EBADF;
        return (Node *)-1;
    }
	while(sat.st_size)
	{
		cur = (Node *)malloc(len);
		if(cur == NULL)
			return (Node *)-1;
		if(root == NULL)
			root = cur;
		else
			pre->link = cur;
		read(fd,buf,len);
		memcpy(cur,buf,len);
		memset(buf,0,len);
		cur->link = NULL;
		pre = cur;
		sat.st_size -= len;
	}
	cur = root;
	return cur;
}

Node *lcreate(int range, int sfd)
{
    Node *root = NULL, *cur, *pre;
    char input[DATA_SIZE];
	int numb;

    if(range == 0)
    {
        printf("initailized an empty list\n");
        return root;
    }
    while(range--)
    {
        cur = (Node *)malloc(sizeof(Node));
        if(cur == NULL)
            return (Node *)-1;
        if(root == NULL)
            root = cur;
        else
            pre->link = cur;
/* can NOT use DATA_SIZE,because an extra '\n' will attach at the end of number*/
        recvfrom(sfd,&numb,sizeof(int),0,NULL,0); /* replace to sizeof(int) */
        cur->number=numb;
		recvfrom(sfd,input,DATA_SIZE,0,NULL,0); /* replace to sizeof(input) */
        strcpy(cur->name,input);
		memset(input,0,sizeof(input));
        cur->link = NULL;
        pre = cur;
        //if(range == 1)
          //  printf("\e[31mone element left\e[0m\n");
    }

    cur = root;
    return cur;
}

/* count start from 0 , NOT 1 !!! */
int modify(Node *head,int where,char *new_value)
{
	Node *cur;
	cur = head;
	
	ori = 1;
	
	while(cur != NULL && where--)
		cur = cur->link;

	strcpy(cur->name, new_value);
	return 0;
}

int isInlist(Node *head, int new_value)
{
	Node *cur;
	cur = head;

	while(cur != NULL)
	{
	 	if(cur->number == new_value)
			break;
		cur=cur->link;
	}

	if(cur == NULL)
		return 0; 			/* not in list */
	else
	{
		errno = EEXIST;
	 	return -1;			/* in list */
	}
}

/*  注释掉的是以前的冗余代码, 已经不能再精简了  ; count from 0 NOT 1 !!!*/
int insert(Node **linkd, int where, char *name)
{
    Node *cur, *new;
	
	ori = 1;
	
   while((cur = *linkd) != NULL && cur->number < where)
		linkd = &cur->link;

    new = (Node *)malloc(sizeof(Node));
    if(new == NULL)
        return -1;

    new->number = where;
	strcpy(new->name, name);
    new->link=cur;

	*linkd = new;
    return 0;
}

int ldelete(Node **linkd, int where)
{
    Node *cur, *pre;

	ori = 1;
    cur = *linkd;
    pre = NULL;

	if(cur != NULL && cur->number == where) /* delete head Node */
    {
	    cur = cur->link;
	    *linkd = cur;
	     return 0;
    }

    while(cur !=NULL && cur->number != where)
    {
         pre = cur;
        cur = cur->link;
    }

    if(cur == NULL)
	{
		errno = EINVAL;
        return -1;
	}

    pre->link = cur->link;
    /* not allocate space yet , so there's no needs to 'free()' */
    return 0;
}

int len(Node *head)
{
    Node  *cur;
    int len = 0;
    cur = head;
    while(cur != NULL)
    {
        len++;
        cur = cur->link;
    }

    return len;
}

int show(Node *head, int fd, SA *client)
{
    Node *cur;
    cur = head;
    int end;

    end=len(head);
    sendto(fd,&end,sizeof(cur->number),0,client,length);
    while(cur != NULL)
    {
        sendto(fd,&cur->number,sizeof(cur->number),0,client,length);
        sendto(fd,cur->name,DATA_SIZE,0,client,length);
        cur = cur->link;
    }
    return 0;
}

/* option: 'l2s': large to small; 's2l': small to large.*/
Node *lrank(Node *head, char *option)
{
    Node *p, *n; /* previous , next */
    Node *cur, *pre, *ne; /* current, previous, next */
    int tmp;

    for(p= head; p != NULL; p = p->link)
    {
        for(n = p->link; n != NULL; n = n->link)
        {
            if(p->number > n->number)
            {
                tmp = n->number;
                n->number = p->number;
                 p->number = tmp;
             }
        }
    }
    if(strcmp(option,"l2s") == 0)
    {
        pre = head;
        cur = head->link;

        while(cur)
        {
            ne = cur->link;
            cur->link = pre;
            pre = cur;
            cur = ne;
        }
        head->link = NULL;
        head  = pre;
    }

    return  head;
}

/* not test yet */
Node *lfind(Node *head, int number)
{
	Node *cur, *out=NULL;
	cur = head;

	while(cur != NULL)
	{
		if(number == cur->number)
		{
			out = malloc(sizeof(Node));
			out = cur;
			break;
		}
		cur =  cur->link;
	}

	return out;
}

int destroy(Node *head)
{
    while(head != NULL)
    {
        free(head);
        head =  head->link;
    }
    return 0;
}

int save(Node *head, const char filename[])
{
	Node *cur;
	int fd;
    cur = head;
	if(ori == 1)
		remove(filename); 		/* namely, write a new list */
	fd=open(filename,O_CREAT|O_RDWR,00644);
	while(cur !=NULL)
	{
		write(fd,cur,sizeof(struct Node));
		cur = cur->link;
	}
	return 0;
}
